package com.iweb.xt.sso.domain;

import com.iweb.xt.common.constants.RedisKey;
import com.iweb.xt.common.model.BusinessCodeEnum;
import com.iweb.xt.common.model.CallResult;
import com.iweb.xt.common.utils.JwtUtil;
import com.iweb.xt.sso.dao.data.User;
import com.iweb.xt.sso.domain.repository.LoginDomainRepository;
import com.iweb.xt.sso.model.param.enums.LoginType;
import com.iweb.xt.sso.model.param.login.LoginParam;
import com.iweb.xt.sso.model.param.user.UserParam;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.mp.bean.result.WxMpOAuth2AccessToken;
import me.chanjar.weixin.mp.bean.result.WxMpUser;
import org.apache.commons.lang3.StringUtils;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletResponse;
import java.util.concurrent.TimeUnit;

public class LoginDomain {
    private LoginDomainRepository loginDomainRepository;
    private LoginParam loginParam;
    private String secretKey="sad&76^asf8**6a";
    public LoginDomain(LoginDomainRepository loginDomainRepository, LoginParam loginParam) {
        this.loginDomainRepository=loginDomainRepository;
        this.loginParam=loginParam;
        
    }

    public CallResult<String> buildQRCodeUrl() {
       String url= loginDomainRepository.buildUrl();
        return CallResult.success(url);
    }

    public CallResult<Object> checkState() {
        boolean isExists=loginDomainRepository.chechState(loginParam.getState());
            return isExists?CallResult.success():CallResult.fail(BusinessCodeEnum.CHECK_PARAM_NO_RESULT.getCode(),BusinessCodeEnum.CHECK_PARAM_NO_RESULT.getMsg());
    }

    public CallResult<Object> login()  {
        try {
//        先从redis里面获取rftoken
            String refreshToken = (String) this.loginDomainRepository.redisTemplate.opsForValue().get(RedisKey.REFRESH_TOKEN);
            WxMpOAuth2AccessToken accessToken = null;
            if (StringUtils.isBlank(refreshToken)) {
//            没有登陆过
                String code = loginParam.getCode();
//            获取刷新的access_token
                accessToken = this.loginDomainRepository.wxMpService.oauth2getAccessToken(code);
                //获取refresh_token
                refreshToken = accessToken.getRefreshToken();
                //存储到redis里面 设置28 14 7 天有效期
                this.loginDomainRepository.redisTemplate.opsForValue().set(RedisKey.REFRESH_TOKEN, refreshToken, 28, TimeUnit.DAYS);
            }
//        之前登陆过 那么直接刷新有效期就可以了
            accessToken = this.loginDomainRepository.wxMpService.oauth2refreshAccessToken(refreshToken);
//        获取微信授权用户信息
            WxMpUser wxMpUser = this.loginDomainRepository.wxMpService.oauth2getUserInfo(accessToken, "zh_CN");
//        获取用户的unionId 判断是否注册过
            String unionId = wxMpUser.getUnionId();
//        到数据库查询一下
            User user = this.loginDomainRepository.createUserDomain(new UserParam()).findUserByUnionId(unionId);
//     如果这个user存在说明 注册过 不存在说明没有注册过
            //给一个标记
            boolean isNew = false;
            if (user == null) {
                //注册
                user = new User();
                Long currentTime = System.currentTimeMillis();
                user.setNickname(wxMpUser.getNickname());
                user.setHeadImageUrl(wxMpUser.getHeadImgUrl());
                user.setSex(wxMpUser.getSex());
                user.setOpenid(wxMpUser.getOpenId());
                user.setLoginType(LoginType.WX.getCode());
                user.setCountry(wxMpUser.getCountry());
                user.setCity(wxMpUser.getCity());
                user.setProvince(wxMpUser.getProvince());
                user.setRegisterTime(currentTime);
                user.setLastLoginTime(currentTime);
                user.setUnionId(wxMpUser.getUnionId());
                user.setArea("");
                user.setMobile("");
                user.setGrade("");
                user.setName(wxMpUser.getNickname());
                user.setSchool("");
                this.loginDomainRepository.createUserDomain(new UserParam()).saveUser(user);
                isNew = true;
            }
            //到这里 应该算是 登陆成功了
//        生成token 存储在redis里面 同时前端也要存储一下到cookie里
            String token = JwtUtil.createJWT(7 * 24 * 60 * 60 * 1000, user.getId(), secretKey);
            this.loginDomainRepository.redisTemplate.opsForValue().set(RedisKey.TOKEN + token, user.getId().toString(), 7, TimeUnit.DAYS);
//        判断是否登陆过 拿到登录token
            String loginToken = (String) this.loginDomainRepository.redisTemplate.opsForValue().get(RedisKey.LOGIN_USER_TOKEN + user.getId());
            if (loginToken != null) {
//            说明在其他设备登陆过
                this.loginDomainRepository.redisTemplate.delete(RedisKey.TOKEN + token);
            }
//        使用user login token
            this.loginDomainRepository.redisTemplate.opsForValue().set(RedisKey.LOGIN_USER_TOKEN + user.getId(), token);
//        给cookie里面添加一份
            HttpServletResponse response = loginParam.getResponse();
            Cookie cookie = new Cookie("t_token", token);
            cookie.setMaxAge(7 * 24 * 3600);
            cookie.setPath("/");
            response.addCookie(cookie);
//      登陆到此成功
            if (isNew) {
//            跟更新最后登录的时间
                user.setLastLoginTime(System.currentTimeMillis());
                this.loginDomainRepository.createUserDomain(new UserParam()).updateLastLoginTime(user);
            }
            return CallResult.success();
        }catch (Exception e){
            e.printStackTrace();
            return CallResult.fail(BusinessCodeEnum.LOGIN_WX_NOT_USER_INFO.getCode(),"授权问题，无法获取用户信息");
        }
    }
}
